package org.rfs.ipodencoder;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import com.trolltech.qt.QThread;

public class QExecuteTask implements Runnable {
	private Process proc;
	private String execCommand;
	private String inputFile, outputFile;
	private QOutputParser outputParser;
	
	public QExecuteTask(QOutputParser outputParser) {
		this.outputParser = outputParser;
	}
	
	public void run() {
		if (execCommand != null) {
			if (System.getProperty("os.name").startsWith("Windows")) {
				execWindows(execCommand);
			} else if (System.getProperty("os.name").startsWith("Mac")) {
				execMac(execCommand);
			} else {
				System.err.println("unsupported OS..."
						+ System.getProperty("os.name"));
				return;
			}
		} else {
			System.err.println("no exec command specified...exiting");
		}
	}
//	
//	public void setOutputParser(OutputParser outputParser) {
//		this.outputParser = outputParser;
//	}
	
	public void setExecCommand(String execCommand) {
		this.execCommand = execCommand;
	}
	
	public void setExecCommand(String execCommand, String inputFile) {
		this.execCommand = execCommand;
		this.inputFile = inputFile;
	}

	public void setExecCommand(String execCommand, String inputFile, String outputFile) {
		this.execCommand = execCommand;
		this.inputFile = inputFile;
		this.outputFile = outputFile;
	}
	
    public boolean execWindows(String winExecCommand) {
        StringTokenizer st = new StringTokenizer(winExecCommand, " ");
        ArrayList<String> execList = new ArrayList<String>(Arrays.asList("cmd.exe","/C"));
        while (st.hasMoreTokens())
        {
            execList.add(st.nextToken());
        }

        return mainExec(execList);
    }

    public boolean execMac(String macExecCommand) {
        StringTokenizer st = new StringTokenizer(macExecCommand, " ");
        //ArrayList<String> execList = new ArrayList<String>(Arrays.asList("/bin/sh","-c"));
        ArrayList<String> execList = new ArrayList<String>();
        while (st.hasMoreTokens())
        {
            execList.add(st.nextToken());
        }

        return mainExec(execList);
    }
    
    private ArrayList<String> replaceInArrayList(ArrayList<String> aList, String source, String dest) {
    	for (int i=0; i<aList.size(); ++i) {
    		if (aList.get(i).toUpperCase().equals(source.toUpperCase())) {
    			aList.set(i, dest);
    		}		
    	}
    	return aList;
    }
	
	private boolean mainExec(ArrayList<String> execCommand) {
//		System.out.println("DEBUG: " + this.execCommand);
        ArrayList<String> executeCommand = null;
		if (inputFile != null) {
        	executeCommand = new ArrayList<String>(replaceInArrayList(execCommand, "@INPUTFILE@", inputFile));
        }
		if (outputFile != null)
			if (executeCommand == null)
				executeCommand = new ArrayList<String>(replaceInArrayList(executeCommand, "@OUTPUTFILE@", outputFile));
			else
				executeCommand = new ArrayList<String>(replaceInArrayList(execCommand, "@OUTPUTFILE@", outputFile));
        
		ProcessBuilder builder;
        try {
            builder = new ProcessBuilder(executeCommand);
            builder.directory(new File("bin"));
            builder.redirectErrorStream(true);

            proc = builder.start();
            
            outputParser.setOutputReader(new BufferedReader(new InputStreamReader(proc.getInputStream())));
            outputParser.setInputWriter(new PrintWriter(proc.getOutputStream()));
            QThread qExec = new QThread(outputParser);
            qExec.start();
            //replace previous 2 lines with "outputParser.start()" to get rid of Qt if needed 
            
            int nResult = proc.waitFor();
            //System.out.println("executor finished...");
            
            if (nResult == 0) {
                return true;
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }
}
